package com.ygq.controller;

import DO.WorkTestTwoDataDO;
import DTO.WorkAnswerDTO;
import DTO.WorkAnswerTADTO;
import VO.*;
import com.alibaba.fastjson.JSON;
import com.ygq.PublishTestService;
import com.ygq.WorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import result.Result;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/student")
@Slf4j
public class WorkTestController {

    @Value("${ygq.file-test2-path}")
    private String path;


    @Autowired
    private PublishTestService publishTestService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private WorkService workService;

    /**
     * 根据班级id获取测试题信息
     * @param classId
     * @return
     */
    @GetMapping("/getworkTest")
    public Result<List<WorkTestByClassIdVO>> getWorkTest(@RequestParam Integer classId,@RequestParam Integer userId){
        return Result.success(publishTestService.getWorkTestByClass(classId,userId));
    }


    /**
     * 学生做题根据试卷id获取题目数据
     * @param workId
     * @return
     */
    @GetMapping("/getworkTestByWorkId")
    public Result<WorkTestByWorkIdVO> getWorkTestByWorkId(Integer workId){
        WorkTestByWorkIdVO workTestByWorkIdVO = publishTestService.gettest1(workId);
        return Result.success(workTestByWorkIdVO);
    }


    // 判断用户是否已经完成题目提交  state 1表示试卷 2表示测试2 2不用管，当1的时候需要查询这个用户是否已经提交当前试卷的答案，如果已经提交返回1即可
    @GetMapping("/isgoingTo")
    public Result<Integer> isgoingTo(@RequestParam Integer state,@RequestParam Integer userId,@RequestParam Integer workId){
        Integer state_work = workService.getStudentState(userId,workId);
        // 1 表示已经提交，但是没有达到结束时间
        // 2 表示保存，可以查看试卷
        // 3 表示已经过了结束时间 需要跳转到另外的vue页面
        return Result.success(state_work);
    }


    // 获取保存的答案数据
    @GetMapping("/getMiddleAnswer")
    public Result<WorkAnswerDTO> getMiddleAnswer(Integer workId, Integer userId){
        String key = "saveWork" + ":" + workId+ ":" + userId;
        String s = stringRedisTemplate.opsForValue().get(key);
        WorkAnswerDTO workAnswerDTO = JSON.parseObject(s, WorkAnswerDTO.class);
        if (workAnswerDTO==null){
            return Result.error("没有数据缓存");
        }
        return Result.success(workAnswerDTO);
    }



    // 提交或者保存答案
    // state 1表示保存答案，2表示提交答案
    // code 600 表示提交或者保存答案时已经超时
    @PostMapping("/submit")
    public Result<String> submitToTest01(@RequestBody WorkAnswerTADTO workAnswerTADTO){
        // redis的key名称命名方法。saveWork + ：+ 作业id+ ： + 用户id
        String key = "saveWork" + ":" + workAnswerTADTO.getWorkAnswerDTO().getWorkId()
                                + ":" + workAnswerTADTO.getWorkAnswerDTO().getUserId();


        // 1. 判断这个时间是否超过这个作业的规定时间，如果超过就报错
        LocalDateTime endTime = workService.getEndTime(workAnswerTADTO.getClassId(),
                workAnswerTADTO.getWorkAnswerDTO().getWorkId());
        if (endTime.isBefore(LocalDateTime.now())){
            // 表示超时，也就是超过截止时间进行提交的，需要进行报错
            return Result.error("已经超过截止时间",600);
        }

        // 2-1，当是保存的情况下
        if(workAnswerTADTO.getState() ==1){
            // 2-2. 如果是保存，则保存到redis里面，步骤，先将其序列化为字符串，将来需要再使用的时候再获取到这个字符串反序列化为对象
            String jsonString = JSON.toJSONString(workAnswerTADTO.getWorkAnswerDTO());
            stringRedisTemplate.opsForValue().set(key,jsonString);


            // 2-3， 设置保存时间到结束时间，结束时间减去当前时间的秒数加上1秒
            // 计算两个时间(试卷结束时间和现在也就是提交时间)之间的Duration
            Duration duration = Duration.between(LocalDateTime.now(),endTime);
            // 获取Duration中的秒数部分
            long expirationTimeInSeconds = duration.getSeconds();

            stringRedisTemplate.expire(key, expirationTimeInSeconds, TimeUnit.SECONDS);
            return Result.success("ok");
        }
        // 当时提交的情况下
        else if (workAnswerTADTO.getState() ==2) {
            Double score = workService.submissAnswer(workAnswerTADTO.getWorkAnswerDTO());
            if (score == -0.1){
                return Result.error("已经提交过了",610);
            }
            // 表示提交答案
            return Result.error(score.toString(),201);
        }
        return Result.error("网络错误");
    }


    /**
     * 用户回显答案
     * @param userId
     * @param workId
     * @return
     */
    @GetMapping("/getStudentAnswer")
    public Result<WorkStudentAnswerViewVO> getStudentAnswer(@RequestParam Integer userId, @RequestParam Integer workId){
        // 首先判断学生是否已经提交过答案
        Integer studentState = workService.getStudentOldState(userId, workId);
        if (studentState==null){
            // 这里表示用户并没有进行提交，需要进行冷处理，然后再返回数据
            return workService.getStudentAnswerButNull(userId,workId);
        }
        return workService.getStudentAnswer(userId,workId);
    }


    /**
     * 获取测试2的题目数据
     * @param workId
     * @param classId
     * @return
     */
    @GetMapping("/getTestWork2")
    public Result<WorkTest2VO> getTestWork2(@RequestParam Integer workId, @RequestParam Integer classId){
        return Result.success(workService.getWorkTest2(workId,classId));
    }


    /**
     * 学生上传测试2 文件
     * @param file
     * @param classId
     * @param workId
     * @param userId
     * @param order
     * @return
     */
    @PostMapping("/submitTest2")
    public Result<String> saveFile(MultipartFile file,Integer classId, Integer workId, Integer userId,Integer order){
        // 先判断是否超过时间
        LocalDateTime endTime = workService.getEndTime(classId, workId);
        if (endTime.isBefore(LocalDateTime.now())){
            return Result.error("超时",201);
        }

        // 判断老师是否已经打分
        Integer score = workService.getIsScores(userId,workId,order);
        if (score != -1){
            return Result.error(score.toString(),202);
        }
        String newName = UUID.randomUUID().toString();
        saveFile(file,path,newName);
        String savePath = path + newName + ".txt";
        WorkTestTwoDataDO workTestTwoDataDO = new WorkTestTwoDataDO();
        workTestTwoDataDO.setWorkId(workId);
        workTestTwoDataDO.setUserId(userId);
        workTestTwoDataDO.setOrder(order);
        workTestTwoDataDO.setAddress(savePath);
        workService.saveWorkTest(workTestTwoDataDO);
        return Result.success("ok");
    }


    /**
     * 获取学生分数，及判断学生题目的批改以及提交情况
     * @param userId
     * @param workId
     * @param number
     * @return
     */
    @GetMapping("/getIsUpload")
    public Result<List<Double>> getIsUpload(Integer userId, Integer workId, Integer number){
        return Result.success(workService.getWorkTest2Score(workId,userId,number));
    }

    /**
     * 保存学生上传的文件
     * @param file 文件
     * @param filePath 文件保存路径
     * @param newFileName 新的文件名
     */
    public void saveFile(MultipartFile file, String filePath, String newFileName) {
        try {
            byte[] bytes = file.getBytes();
            Path path = Paths.get(filePath + File.separator + newFileName + ".txt");
            Files.write(path, bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
